package org.zjx.common.route;


import org.jetbrains.annotations.NotNull;
import org.zjx.common.route.bean.Address;
import org.zjx.common.route.bean.Coordinate;
import org.zjx.common.route.routes.FlyingCharmsRoute;
import org.zjx.common.route.routes.FlyingFlagsRoute;
import org.zjx.common.route.routes.RunRoute;

import java.util.*;
import java.util.stream.Collectors;

public class RouteManager {
    private final List<IRoute> routes;
    private final Address startAddress;

    public RouteManager(Address start) {
        routes = new ArrayList<>();
        startAddress = start;
        routes.addAll(getFlyingCharmsRoutes(startAddress));
    }

    public void addRoute(IRoute route) {
        routes.add(route);
    }

    public void addRoutes(List<IRoute> routes) {
        this.routes.addAll(routes);
    }

    public void addWayPointRoutes(List<IRoute> routes) {
        // 添加三种类型的连接路线
        List<IRoute> newRoutes = new ArrayList<>();
        newRoutes.addAll(connectRoutesWithinSameCity(this.routes, routes)); // 连接现有路线和新路线
        newRoutes.addAll(connectRoutesWithinSameCity(routes, routes));      // 新路线之间的连接
        newRoutes.addAll(routes);                                          // 直接添加新路线
        this.routes.addAll(newRoutes);
    }

    /**
     * 更精确的去重方法（基于起点和终点的坐标+城市）
     */
    private List<IRoute> deduplicateRoutes(List<IRoute> routes) {
        Map<String, IRoute> uniqueRoutes = new LinkedHashMap<>();

        for (IRoute route : routes) {
            String key = buildRouteKey(route);
            uniqueRoutes.putIfAbsent(key, route);
        }

        return new ArrayList<>(uniqueRoutes.values());
    }

    private String buildRouteKey(IRoute route) {
        return String.format("%s|%d|%d|%s|%d|%d",
                route.getStart().getCity(),
                route.getStart().getX(),
                route.getStart().getY(),
                route.getEnd().getCity(),
                route.getEnd().getX(),
                route.getEnd().getY()
        );
    }

    public List<IRoute> getFlyingCharmsRoutes(Address start) {
        List<IRoute> routeList = new ArrayList<>();
        routeList.add(new FlyingCharmsRoute(start, "长寿村"));
        routeList.add(new FlyingCharmsRoute(start, "西梁女国"));
        routeList.add(new FlyingCharmsRoute(start, "宝象国"));
        routeList.add(new FlyingCharmsRoute(start, "朱紫国"));
        routeList.add(new FlyingCharmsRoute(start, "长安城"));
        routeList.add(new FlyingCharmsRoute(start, "建邺城"));
        routeList.add(new FlyingCharmsRoute(start, "傲来国"));
        return routeList;
    }


    public List<IRoute> getFlyingFlagsRoutes(String name, List<Coordinate> coordinates) {
        if (coordinates == null || coordinates.isEmpty()) return Collections.emptyList();
        List<IRoute> routeList = new ArrayList<>();
        for (Coordinate coordinate : coordinates) {
            IRoute route = new FlyingFlagsRoute(startAddress, new Address(name, coordinate.getX(), coordinate.getY()));
            routeList.add(route);
        }
        return routeList;
    }

    public List<IRoute> findPath(Address endAddress) {
        routes.addAll(getStartEndRoutes(endAddress));

        // 使用LinkedHashSet去重（保持插入顺序）
//        List<IRoute> deduplicated = new ArrayList<>(new LinkedHashSet<>(newRoutes));

        // 精确去重：基于起点和终点的坐标+城市进行判断
        List<IRoute> deduplicated = deduplicateRoutes(routes);

        DijkstraPathFinder dijkstraPathFinder = new DijkstraPathFinder();
        return dijkstraPathFinder.findPath(deduplicated, startAddress, endAddress);
    }

    public List<IRoute> getStartEndRoutes(Address endAddress) {
        List<IRoute> startRoutes = routes.stream()
                .filter(route ->
                        route.getStart().getCity().equals(startAddress.getCity())
                )
                .collect(Collectors.toList());
        List<IRoute> endRoutes = routes.stream()
                .filter(route ->
                        route.getEnd().getCity().equals(endAddress.getCity())
                )
                .collect(Collectors.toList());

        return getIRoutes(endAddress, startRoutes, endRoutes);
    }


    /**
     * 连接两个路线集合：用start集合的终点与end集合的起点在同一城市的路线生成新步行路线
     * @param start 起点路线集合（新路线的起点来自这些路线的终点）
     * @param end 终点路线集合（新路线的终点来自这些路线的起点）
     * @return 生成的所有新路线集合（排除自连接和坐标相同的情况）
     */
    public List<IRoute> connectRoutesWithinSameCity(List<IRoute> start, List<IRoute> end) {
        List<IRoute> result = new ArrayList<>();

        // 按起点城市对end路线分组，优化查找效率
        Map<String, List<IRoute>> endRoutesByStartCity = end.stream()
                .collect(Collectors.groupingBy(route -> route.getStart().getCity()));

        for (IRoute currentRoute : start) {
            Address currentEnd = currentRoute.getEnd();
            List<IRoute> possibleNextRoutes = endRoutesByStartCity.get(currentEnd.getCity());

            if (possibleNextRoutes != null) {
                for (IRoute nextRoute : possibleNextRoutes) {
                    // 跳过自连接（同一个Route实例）
                    if (currentRoute == nextRoute) continue;

                    // 跳过坐标相同的连接
                    if (currentEnd.getX() == nextRoute.getStart().getX() &&
                            currentEnd.getY() == nextRoute.getStart().getY()) {
                        continue;
                    }

                    // 创建新步行路线
                    result.add(new RunRoute(currentEnd, nextRoute.getStart()));
                }
            }
        }
        return result;
    }

    @NotNull
    private List<IRoute> getIRoutes(Address endAddress, List<IRoute> startRoutes, List<IRoute> endRoutes) {
        List<IRoute> result = new ArrayList<>();
        for (IRoute route : startRoutes) {
            if (route instanceof FlyingCharmsRoute || route instanceof FlyingFlagsRoute) continue;
            RunRoute runRoute = new RunRoute(startAddress, route.getStart());
            result.add(runRoute);
        }

        for (IRoute route : endRoutes) {
            RunRoute runRoute = new RunRoute(route.getEnd(), endAddress);
            result.add(runRoute);
        }

        if (startAddress.getCity().equals(endAddress.getCity())) {
            RunRoute runRoute = new RunRoute(startAddress, endAddress);
            result.add(runRoute);
        }
        return result;
    }


    public static void main(String[] args) {
        Address start = new Address("江南野外", 34, 45);
        Address end = new Address("长安城", 123, 24);


        RouteManager routeManager = new RouteManager(start);

        List<Coordinate> coordinates = new ArrayList<>();
        coordinates.add(new Coordinate(134, 45));
        coordinates.add(new Coordinate(34, 145));
        coordinates.add(new Coordinate(64, 85));
        List<IRoute> routes = routeManager.getFlyingFlagsRoutes("长安城", coordinates);
        routeManager.addRoutes(routes);

        List<IRoute> path = routeManager.findPath(end);

        System.out.printf("从 %s 到 %s 的最短路径：%n", start, end);
        path.forEach(System.out::println);
        System.out.printf("预计总耗时：%d秒%n%n", path.stream().mapToInt(IRoute::getTime).sum());
    }

}
